package com.gitee.melin.bee.core.jdbc.parser;

import com.gitee.melin.bee.core.jdbc.enums.DataSourceType;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.commons.lang3.StringUtils;

public class PostgreSQLURLParser extends AbstractURLParser {

    private static final int DEFAULT_PORT = 5432;

    private DataSourceType dataSourceType;

    public PostgreSQLURLParser(DataSourceType dataSourceType) {
        this.dataSourceType = dataSourceType;
    }

    @Override
    protected URLLocation fetchDatabaseHostsIndexRange(String url) {
        int hostLabelStartIndex = url.indexOf("//");
        int hostLabelEndIndex = url.indexOf("/", hostLabelStartIndex + 2);
        return new URLLocation(hostLabelStartIndex + 2, hostLabelEndIndex);
    }

    @Override
    protected URLLocation fetchDatabaseNameIndexRange(String url) {
        int hostLabelStartIndex = url.indexOf("//");
        int hostLabelEndIndex = url.indexOf("/", hostLabelStartIndex + 2);
        int databaseStartTag = url.indexOf("/", hostLabelEndIndex);
        int databaseEndTag = url.indexOf("?", databaseStartTag);
        if (databaseEndTag == -1) {
            databaseEndTag = url.length();
        }
        return new URLLocation(databaseStartTag + 1, databaseEndTag);
    }

    @Override
    public JdbcURLInfo parse(String url) {
        URLLocation location = fetchDatabaseHostsIndexRange(url);
        String hosts = url.substring(location.startIndex(), location.endIndex());
        String[] hostSegment = hosts.split(",");
        if (hostSegment.length > 1) {
            StringBuilder sb = new StringBuilder();
            for (String host : hostSegment) {
                URI uri = parseHost(host);
                int port = uri.getPort() == -1 ? DEFAULT_PORT : uri.getPort();

                sb.append(uri.getHost() + ":" + port + ",");
            }
            if (',' == sb.charAt(sb.length() - 1)) {
                sb.deleteCharAt(sb.length() - 1);
            }

            String dbOptions = StringUtils.substringAfter(url, "?");
            return new JdbcURLInfo.Builder(sb.toString())
                    .dsType(dataSourceType)
                    .dbInstance(fetchDatabaseNameFromURL(url))
                    .dbOptions(dbOptions)
                    .build();
        } else {
            URI uri = parseHost(hostSegment[0]);
            int port = uri.getPort() == -1 ? DEFAULT_PORT : uri.getPort();
            String dbOptions = StringUtils.substringAfter(url, "?");

            return new JdbcURLInfo.Builder(uri.getHost() + ":" + port)
                    .dsType(dataSourceType)
                    .dbInstance(fetchDatabaseNameFromURL(url))
                    .dbOptions(dbOptions)
                    .build();
        }
    }

    private URI parseHost(String host) {
        try {
            return new URI("proto://" + host);
        } catch (URISyntaxException e) {
            throw new IllegalArgumentException(e);
        }
    }
}
